package org.tinyweb.core;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tinyweb.render.Render;

public class Handler {
    private static final Logger LOGGER = LoggerFactory.getLogger(Handler.class);
    private static final String DEFAULT_METHOD_NAME = "execute";
    private static final Handler handle = new Handler();
    private String startupPackage;
    private String rootPackage;
    private String encoding;
    
    private Handler(){
        
    }

    public static Handler instance(){
        return handle;
    }

    void init(String startupPackage,String rootPackage,String encoding){
        this.startupPackage = startupPackage;
        this.rootPackage = rootPackage;
        this.encoding = encoding;
    }

    
    /**
     * 扫描loadOnStartup包，并执行相应的方法
     */
    public void startupOnLoadHandle(){
        if (startupPackage==null){
            return;
        }
        String resourceName = startupPackage.replace(".", "/");
        try {
            URL url = Handler.class.getClassLoader().getResource(resourceName);
            File packageFile = new File(url.toURI());
            File[] files = packageFile.listFiles();
            for (File file : files) {
                String fileFullName = file.getName();
                String extName = fileFullName.substring(fileFullName.lastIndexOf("."),fileFullName.length());
                if (".class".endsWith(extName)){
                    String fileName = fileFullName.split(".class")[0];
                    String className = startupPackage + '.' + fileName;
                    doStartupMethod(className);
                }
            }
        } catch (Exception e){
            LOGGER.error(e.getMessage(),e);
        }
    }
    
    /**
     * 执行LoadOnStartup的方法
     * @param className
     * @throws Exception
     */
    private static void doStartupMethod(String className){
        try{
            Class<?> executeClass = Class.forName(className);
            Constructor<?> cons = executeClass.getDeclaredConstructor();
            int mod = cons.getModifiers();
            if (Modifier.isPrivate(mod)){
                Method[] methods = executeClass.getMethods();
                String instanceMethodName = null;
                for (Method method : methods) {
                    if(method.getGenericReturnType().equals(executeClass)){
                        instanceMethodName = method.getName();
                    }
                }
                if(instanceMethodName!=null){
                    Method instanceMethod = executeClass.getMethod(instanceMethodName);
                    instanceMethod.invoke(executeClass); 
                }
            } else if(Modifier.isPublic(mod)){
                Method executeMethod = executeClass.getMethod(DEFAULT_METHOD_NAME);
                executeMethod.invoke(cons.newInstance());
            } 
        } catch (Exception e){
            LOGGER.error(e.getMessage(), e);
        }
    }
    
    /**
     * 控制器处理
     * @param request
     * @param response
     */
    public void controllerHandle(HttpServletRequest request,HttpServletResponse response){
        try {
            request.setCharacterEncoding(encoding);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String methodName = request.getParameter("method");
        String uri = request.getRequestURI();
        String contextPath = request.getContextPath();
        uri = uri.substring(contextPath.length(),uri.length());
        String subPackageName = uri.substring(0, uri.lastIndexOf("/"));
        subPackageName = subPackageName.replace("/", ".");
        String className = uri.substring(uri.lastIndexOf("/")+1, uri.lastIndexOf("."));
        String firstChar = className.substring(0,1);
        String surplusChar = className.substring(1, className.length());
        className = firstChar.toUpperCase()+surplusChar;
        className = rootPackage + subPackageName + "." + className;
        try {
            Class<?> mappingClass = Class.forName(className);
            Object instanceClass = mappingClass.newInstance();
            Controller controller = (Controller) instanceClass;
            controller.init(request, response);
            Method method;
            if(methodName!=null){
                method = mappingClass.getMethod(methodName);
            } else {
                method = mappingClass.getMethod(DEFAULT_METHOD_NAME);
            }
            method.invoke(instanceClass);  
            //渲染视图
            Render render = controller.getRender();
            if (render != null){
                render.render();
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(),e);
        }
    }
}
